/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package classPack;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import tela.PanelConversa;
import tela.Principal;

/**
 *
 * @author Eu
 */
public class Conexao implements Runnable {

    public static final int porta = 4444;
    private static Conexao secao = null;
    private boolean ligado;
    private Thread trCon = null;
    private Encrypt crypt = null;
    private Principal telaPrincipal = null;

    private Conexao(Principal telaPrincipal) {
        // Passar lista de conversas
        crypt = Encrypt.getInstance();
        this.telaPrincipal = telaPrincipal;
        ligado = true;
        trCon = new Thread(this);
        trCon.start();
    }

    public static Conexao getInstance(Principal telaPrincipal) {
        if (secao == null) {
            secao = new Conexao(telaPrincipal);
        }
        return secao;
    }

    public static Conexao getInstance() {
        if (secao != null) {
            return secao;
        }
        return null;
    }

    public boolean isLigado() {
        return ligado;
    }

    public void toggleLigado() {
        ligado = !ligado;
    }

    public void Ligar() {
        ligado = true;
    }

    public void Desligar() {
        ligado = false;
    }

    @Override
    public void run() {
        System.out.println("Thread - entrou");
        ServerSocket socketAbrir = null;
        Socket server = null;
        try {
            socketAbrir = new ServerSocket(porta);
            socketAbrir.setSoTimeout(1000);
        } catch (IOException ex) {
            System.out.println("Erro ao abrir a porta... =/");
        }
        while (ligado) {
            try {
                server = socketAbrir.accept();
                server.setSoLinger(true, 0);

                inputConn inptConn = new inputConn(server);
                Thread tInptConn = new Thread(inptConn);
                tInptConn.start();
            } catch (Exception e) {
            }
        }
        try {
            socketAbrir.close();
        } catch (Exception e) {
        }

    }

    public void Enviar(String ipDestino, String mensagem) {
        Socket connCliente = null;
        BufferedWriter bfr = null;
        try {
            connCliente = new Socket(ipDestino, porta);
            connCliente.setSoTimeout(1000);
            connCliente.setSoLinger(false, 0);
            bfr = new BufferedWriter(new OutputStreamWriter(connCliente.getOutputStream()));
            System.out.println("Enviando - " + ipDestino + " - " + mensagem);
            mensagem = crypt.getEncryptMsg(mensagem, Chave.getChave());
            bfr.write(mensagem);
            bfr.flush();
        } catch (Exception e) {
        } finally {
            try {
                bfr.close();
                connCliente.close();
            } catch (Exception e) {
            }
        }
    }

    public void enviarMensagem(Usuario usuDestino, String mensagem) {
        Enviar(usuDestino.getIpUsuario(), mensagem);
    }

    public void entreiTodos() {
        for (Usuario user : telaPrincipal.usuarios.values()) {
            if (!user.equals(Principal.logado)) {
                estouOnline(user);
            }
        }
    }

    public void saindoTodos() {
        for (Usuario user : telaPrincipal.usuarios.values()) {
            if (user.isOnline() && !user.equals(Principal.logado)) {
                estouOffLine(user);
                user.setOnline(false);
            }
        }
    }

    public void estouOnline(Usuario usuDesUsuario) {
        enviarMensagem(usuDesUsuario, "1;");
    }

    public void estouOffLine(Usuario usuDesUsuario) {
        enviarMensagem(usuDesUsuario, "2;");
    }

    public void solicitarUsu(Usuario usuSolicitar) {
        Enviar(usuSolicitar.getIpUsuario(), "3;" + Principal.logado.gerarString());
    }

    public void aceitarUsu(Usuario usuAceito) {
        usuAceito.setAceito(true);
        Conversa nova = new Conversa(usuAceito.getNome());
        nova.addUsuario(usuAceito);
        nova.gerarNome();
        Enviar(usuAceito.getIpUsuario(), "3.1;"
                + Principal.logado.getNome() + ";"
                + nova.getNome());
    }

    public void enviarConviteGrupo(Conversa grupo) {
        if (grupo != null) {
            for (Usuario user : grupo.getUsuarios().values()) {
                if (!user.equals(Principal.logado)) {
                    Enviar(user.getIpUsuario(), "4;" + grupo.gerarString());
                }
            }
        }
    }

    public void sairGrupo(Conversa grupo) {
        for (Usuario user : grupo.getUsuarios().values()) {
            if (!user.equals(telaPrincipal.logado)) {
                enviarMensagem(user, "0;" + grupo.getNome() + ";"
                        + "‼Saindo do grupo‼");
                enviarMensagem(user, "4.1;" + grupo.getNome() + ";"
                        + telaPrincipal.logado.getIpUsuario());
            }
        }
    }

    public void incluirUsuarioGrupo(Conversa grupo, Usuario userInc) {
        for (Usuario user : grupo.getUsuarios().values()) {
            enviarMensagem(user, "4.2;"
                    + grupo.getNome() + ";"
                    + userInc.gerarString());
        }
    }

    public void solicitarAtualizacaoGrupo(Conversa grupo) {
        for (Usuario user : grupo.getUsuarios().values()) {
            if (user.isOnline() && !user.equals(telaPrincipal.logado)) {
                enviarMensagem(user, "4.3;" + grupo.getNome());
            }
        }
    }

    public void enviarAtualizacao(Conversa grupo, Usuario solicitou) {
        enviarMensagem(solicitou, "4.4;"
                + grupo.getNome() + ";"
                + grupo.gerarString());
    }

//mensagens via socket inicio;
    //
    private class inputConn implements Runnable {

        private Socket server;
        private String linha;

        public inputConn(Socket server) {
            this.server = server;
        }

        @Override
        public void run() {
            try {
                BufferedReader bfReader = new BufferedReader(new InputStreamReader(server.getInputStream()));
                linha = bfReader.readLine();
                //Enviar a mensagem recebida do socket...
                Encrypt crypt = Encrypt.getInstance();
                linha = crypt.getDecryptMsg(linha, Chave.getChave(server.getInetAddress().getHostAddress()));
                System.out.println("Recebi-" + server.getInetAddress().getHostAddress() + "-" + linha);
                centralComando(linha, server);
                server.close();
            } catch (Exception e) {
                System.out.println(e);
            }
        }

        public void centralComando(String comando, Socket server) {
            String partes[] = comando.split(";");
            Usuario user = telaPrincipal.usuarios.get(server.getInetAddress().getHostAddress());

            if (partes[0].equals("0")) {  //mensagem recebida
                Conversa recebida = telaPrincipal.conversas.get(partes[1]);
                if (user != null && recebida != null) {
                    Mensagem msg = new Mensagem(user, partes[2]);
                    recebida.addMensagem(msg);
                    if (recebida.getJanela() == null) {
                        PanelConversa novaTela
                                = new PanelConversa(telaPrincipal.jTbPnConversas, recebida);
                        recebida.setJanela(novaTela);
                        recebida.montarTela();
                    }
                    if (!recebida.getJanela().isVisible()) {
                        recebida.getJanela().mostrar();
                    }
                }
            }
            if (partes[0].equals("1")) {  //contato Online
                if (user != null && !user.isOnline()) {
                    user.toggleOnline();
                    if (!user.isBloqueado()) {
                        Conexao.getInstance().enviarMensagem(user, "1;");
                    }
                    telaPrincipal.popularSelectList();
                }
            }
            if (partes[0].equals("2")) {  //contato offline
                if (user != null && user.isOnline()) {
                    user.toggleOnline();
                }
                telaPrincipal.popularSelectList();
            }
            if (partes[0].equals("3")) {  //novo contato
                try {
                    Usuario recebido = (Usuario) Classes.carregarString(partes[1]);
                    recebido.setAceito(false);
                    telaPrincipal.usuarios.put(recebido.getIpUsuario(), recebido);
                    telaPrincipal.popularSelectList();
                } catch (Exception e) {
                }
            }
            if (partes[0].equals("3.1")) {  //novo contato aceitar
                try {
                    //Usuario recebido = (Usuario) Classes.carregarString(partes[1]);
                    user.setAceito(true);
                    user.setOnline(true);
                    user.setNome(partes[1]);
                    telaPrincipal.usuarios.put(user.getIpUsuario(), user);
                    Conversa nova = new Conversa(user.getNome());
                    nova.addUsuario(user);
                    nova.setNome(partes[2]);
                    telaPrincipal.conversas.put(nova.getNome(), nova);
                    telaPrincipal.popularSelectList();
                } catch (Exception e) {
                }
            }
            if (partes[0].equals("4")) {  //novo grupo
                try {
                    Conversa recebido = (Conversa) Classes.carregarString(partes[1]);
                    recebido.setAceito(true);
                    for (Usuario atual : recebido.getUsuarios().values()) {
                        if (!telaPrincipal.usuarios.containsKey(atual.getIpUsuario())) {
                            telaPrincipal.usuarios.put(atual.getIpUsuario(), atual);
                        }
                    }
                    telaPrincipal.conversas.put(recebido.getNome(), recebido);
                    telaPrincipal.popularSelectList();
                } catch (Exception e) {
                }
            }
            if (partes[0].equals("4.1")) { //usuario saiu do grupo
                try {
                    Conversa atual = telaPrincipal.conversas.get(partes[1]);
                    if (atual != null) {
                        atual.getUsuarios().remove(partes[2]);
                        atual.getJanela().montarUsuarios();
                        if (atual.isSingleUser()) {
                            telaPrincipal.conversas.remove(atual.getNome());
                            telaPrincipal.popularSelectList();
                            atual.addMensagem(new Mensagem(
                                    telaPrincipal.logado,
                                    "Grupo desfeito por falta de usuarios..."));
                            atual.getJanela().fecharJanela();
                        }
                    }
                } catch (Exception e) {
                }
            }
            if (partes[0].equals("4.2")) { //usuario entrou no grupo
                try {
                    Conversa atual = telaPrincipal.conversas.get(partes[1]);
                    Usuario entrar = (Usuario) Usuario.carregarString(partes[2]);
                    Usuario busca = telaPrincipal.usuarios.get(entrar.getIpUsuario());
                    if (busca != null) {
                        entrar = busca;
                    }
                    telaPrincipal.usuarios.put(entrar.getIpUsuario(), entrar);
                    atual.addUsuario(entrar);
                    atual.getJanela().montarUsuarios();
                } catch (Exception e) {
                }
            }

            if (partes[0].equals("4.3")) { //usuario pediu para atualizar o grupo
                try {
                    Conversa atual = telaPrincipal.conversas.get(partes[1]);
                    if (atual != null) {
                        enviarAtualizacao(atual, user);
                    }
                } catch (Exception e) {
                }
            }

            if (partes[0].equals("4.4")) { //receber atualizacao
                try {
                    Conversa atual = telaPrincipal.conversas.get(partes[1]);
                    Conversa nova = (Conversa) Conversa.carregarString(partes[2]);
                    if (nova.getQuantidadeMsg() >= atual.getQuantidadeMsg()) {
                        atual.apagarHistorico();
                        atual.setMensagens(nova.getMensagens());
                        atual.montarTela();
                    } else {
                        enviarAtualizacao(atual, user);
                    }
                } catch (Exception e) {
                }
            }
        }
    }
}
